package com.atguigu.gmall.seckill.listener;/*
 * @author: XueYouPeng
 * @time: 23.8.3 上午 10:07
 */

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.GmallConstant;
import com.atguigu.gmall.rabbit.constant.RabbitConstant;
import com.atguigu.gmall.seckill.entity.SeckillQueueMsg;
import com.atguigu.gmall.seckill.service.SeckillGoodsService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class SeckillOrderQueueListener {

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private RedisTemplate<String , String> redisTemplate;

    @RabbitListener(bindings = {
            @QueueBinding(value = @Queue(value = "RabbitConstant.SECKILL_ORDER_QUEUE", durable = "true"),
            exchange = @Exchange(value = RabbitConstant.SECKILL_ORDER_EXCHANGE , type = ExchangeTypes.DIRECT),
            key = { RabbitConstant.SECKILL_ORDER_ROUTING_KEY })
    })
    public void seckillOrderQueueListener(Message message , Channel channel){

        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        byte[] body = message.getBody();
        String msgJSON = new String(body) ;
        SeckillQueueMsg seckillQueueMsg = JSON.parseObject(msgJSON, SeckillQueueMsg.class);

        try {
            // 1、进行数据库库存的扣减
            seckillGoodsService.deduceStock(seckillQueueMsg);

            // 2、生成临时订单数据，将其存储到Redis中
            seckillGoodsService.saveOrderInfoToRedis(seckillQueueMsg);

            // 3、Redis中的秒杀商品的库存扣减
            seckillGoodsService.redisStockCountDeduce(seckillQueueMsg);
            log.info("秒杀抢单成功....");
        } catch (Exception e) {
            e.printStackTrace();
            String redisOrderKey  = GmallConstant.REDIS_SECKILL_ORDER + seckillQueueMsg.getSeckillCode();
            redisTemplate.opsForValue().set(redisOrderKey , GmallConstant.REDIS_NULL_VALUE , 2 , TimeUnit.DAYS);
        }

        //4.进行手动应答
        try {
            channel.basicAck(deliveryTag , true);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}
